package shm

/*
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

typedef struct {
	int64_t 	ret;
	int			status;
	char 		*err_msg;
} my_shm_op_result_t;

my_shm_op_result_t *
my_shm_open(const char *name, int flag, unsigned int mode)
{
	my_shm_op_result_t *res =
		(my_shm_op_result_t *)malloc(sizeof(my_shm_op_result_t));
	if (res == NULL) {
		return NULL;
	}

	bzero(res, sizeof(my_shm_op_result_t));

	res->status = shm_open(name, flag, mode);
	if (res->status == -1) {
		res->err_msg = strerror(errno);
	} else {
		res->ret = res->status;
		res->status = 0;
	}

	return res;
}

my_shm_op_result_t *
my_shm_unlink(const char *name)
{
	my_shm_op_result_t *res =
		(my_shm_op_result_t *)malloc(sizeof(my_shm_op_result_t));
	if (res == NULL) {
		return NULL;
	}

	bzero(res, sizeof(my_shm_op_result_t));

	res->status = shm_unlink(name);
	if (res->status == -1) {
		res->err_msg = strerror(errno);
	}

	return res;
}

void
my_shm_op_result_free(my_shm_op_result_t *res)
{
	free(res);
}

#cgo linux LDFLAGS: -lrt
*/
import "C"
import (
	"errors"
	"os"
)

func ShmOpen(fileName string, flag int, mode os.FileMode) (*os.File, error) {
	var res *C.my_shm_op_result_t
	res = C.my_shm_open(C.CString(fileName), C.int(flag), C.uint(mode))
	if res == nil {
		return nil, errors.New("get nil result from C.my_shm_open")
	}

	defer C.my_shm_op_result_free(res)

	if res.status != 0 {
		if res.err_msg != nil {
			return nil, errors.New(C.GoString(res.err_msg))
		}

		return nil, errors.New("unknown error")
	}

	return os.NewFile(uintptr(res.ret), fileName), nil
}

func ShmUnlink(fileName string) error {
	var res *C.my_shm_op_result_t
	res = C.my_shm_unlink(C.CString(fileName))
	if res == nil {
		return errors.New("get nil result from C.my_shm_unlink")
	}

	defer C.my_shm_op_result_free(res)

	if res.status != 0 {
		if res.err_msg != nil {
			return errors.New(C.GoString(res.err_msg))
		}

		return errors.New("unknown error")
	}

	return nil
}
